客户端和服务器的传输使用 HTTP 协议,HTTP 协议是无状态的。
无状态,就是每一次请求响应都是独立的,服务器不知道这一次请求,和之前某次请求是不是同一个人。
有什么办法能够让服务器标识出请求的身份呢?
服务器按照下面的流程来认证客户端的身份:
服务器发扬了认证不认人的优良传统,就可以很轻松的识别身份了。
![[image-20200417161950450.png]]
但是,用户不可能只在一个网站登录,于是客户端会收到来自各个网站的出入证,因此,就要求客户端要有一个类似于卡包的东西,能够具备下面的功能:
能够满足上面所有要求的,就是 cookie,cookie 类似于一个卡包,专门用于存放各种出入证,并有着一套机制来自动管理这些证件。
cookie 是浏览器中特有的一个概念,它就像浏览器的专属卡包,管理着各个网站的身份信息。
每个 cookie 就相当于是属于某个网站的一个卡片,它记录了下面的信息:
key:键value:值domain:域,表达这个 cookie 是属于哪个网站的
path:路径,表达这个 cookie 是属于该网站的哪个基路径的
secure:是否使用安全传输(HTTPS)
expire:过期时间,表示该 cookie 在什么时候过期,绝对时间
Fri, 17 Apr 2020 09:35:59 GMTmax-age:过期时间,表示该 cookie 在什么时候过期,相对于当前时间
expire 和 max-age 通常仅设置一个即可expire 和 max-age 都没有,则表示会话结束后过期(对于大部分浏览器而言,关闭所有浏览器窗口意味着会话结束)httponly:设置 cookie 是否仅能用于传输。如果设置了该值,表示该 cookie 仅能用于传输,而不允许在客户端通过 JS 读写
sameSite:
Strict:严格,请求来自设置 cookie 的站点才会携带该 cookieLax:宽松,cookie 不会在跨站请求中被发送,如:加载图像或框架(frame)的请求。但 cookie 在用户从外部站点导航到源站时,cookie 也会被发送(例如,访问一个链接)。这是 SameSite 属性未被设置时的默认值。None:无,浏览器在跨站和同站请求中均会发送 cookie。在设置这一属性值时,必须同时设置 Secure 属性,就像这样:SameSite=None; Secure。如果未设置 Secure,则会出现 [[#^b7756d|以下错误]]。SameSite=None 但未设置 Secure 的报错: ^b7756d
Cookie "myCookie" rejected because it has the "SameSite=None" attribute but is missing the "secure" attribute.
This Set-Cookie was blocked because it had the "SameSite=None" attribute but did not have the "Secure" attribute, which is required in order to use "SameSite=None".
当浏览器向服务器发送一个请求的时候,它会瞄一眼自己的卡包,看看哪些卡片适合附带捎给服务器
如果一个 cookie 同时满足以下条件,则这个 cookie 会被附带到请求中:
yuanjin.tech,则可以匹配的请求域是 yuanjin.tech、www.yuanjin.tech、blogs.yuanjin.tech 等www.yuanjin.tech,则只能匹配 www.yuanjin.tech 这样的请求域/news,则可以匹配的请求路径可以是 /news、/news/detail、/news/a/b/c 等等,但不能匹配 /blogssecure 属性是 true,则请求协议必须是 HTTPS,否则不会发送该 cookiesecure 属性是 false,则请求协议可以是 HTTP,也可以是 HTTPSsameSite 规则是否符合具体加入的方式是,浏览器会将符合条件的 cookie,自动放置到 Cookie 请求头中,值的格式是 key1=value1; key2=value2; ...,每一个键值对就是一个符合条件的 cookie。
cookie 中包含了重要的身份信息,永远不要把你的 cookie 泄露给别人!否则,他人就拿到了你的证件,就具备了为所欲为的可能性。
由于 cookie 是保存在浏览器端的,同时,很多证件又是服务器颁发的
所以,cookie 的设置有两种模式:
服务器可以通过设置响应头,来告诉浏览器应该如何设置 cookie,响应头按照下面的格式设置:
Set-Cookie: cookie1
Set-Cookie: cookie2
通过这种模式,就可以在一次响应中设置多个 cookie 了。其中,每个 cookie 的格式如下:
key=value; path=?; domain=?; expire=?; max-age=?; secure; httponly
每个 cookie 除了键值对是必须要设置的,其他的属性都是可选的,并且顺序不限。
当这样的响应头到达客户端后,浏览器会自动的将 cookie 保存到卡包中,如果卡包中已经存在一模一样的卡片(其他信息,如 path、domain 相同),则会自动的覆盖之前的设置。
如何删除浏览器的一个 cookie 呢?
如果要删除浏览器的 cookie,只需要让服务器响应一个同样的域、同样的路径、同样的 key,只是时间已经过期的 cookie 即可:
set-cookie: token=; domain=yuanjin.tech; path=/; max-age=-1
所以,删除 cookie 其实就是修改 cookie 让其过期。浏览器按照要求修改了 cookie 后,会发现 cookie 已经过期,于是自然就会删除了。
无论是修改还是删除,都要注意 cookie 的域和路径,因为完全可能存在域或路径不同,但 key 相同的 cookie,因此无法仅通过 key 确定是哪一个 cookie
既然 cookie 是存放在浏览器端的,所以浏览器向 JS 公开了接口,让其可以设置 cookie:
document.cookie = "key=value; path=?; domain=?; expire=?; max-age=?; secure";
可以看出,在客户端设置 cookie,和服务器设置 cookie 的格式一样,只是有下面的不同:
httponlypath 的默认值
domain 的默认值,和 path 同理
cookie 的数据都是存到客户端的,很不安全,session 基于 cookie 实现。
其原理就是:服务器开辟一块空间(可以是狭义的 session 内存空间,也可以是 Redis 等缓存数据库),将该用户相关的数据存储到该空间,给此空间分配一个 session id(sid)并通过 cookie 返回给客户端,下次该客户端请求服务器就会携带 sid,服务器可以通过 sid 获取空间中存储的内容
session 会占用服务器资源,会话结束就要将其销毁,通常有两种方式:
cookie、sessionStorage、localStorage 都是保存本地数据的方式。
cookie 用于标识请求端身份信息
set-cookie 字段时,浏览器会自动保存 cookie 的值;浏览器发送请求时,会附带匹配的 cookie 到请求头中。这些默认行为,使得 cookie 长期以来担任着维持登录状态的责任。HTML5 新增了 sessionStorage 和 localStorage,前者用于保存会话级别的数据,后者用于更持久的保存数据。
[[004.浏览器离线存储|浏览器离线存储]]
cookie 和 session:
token(如:[[005.JWT|JWT]]):